﻿using DzInfo.Model.KD;
using DzInfo.Tools;
using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using Kingdee.K3.FIN.App.Core;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace DzInfo.SerivesPlugin.Zr
{
    [Description("中润:销售出库提交时自动生成组织间调拨单、退回单"), HotUpdate]
    public class AutoTransferDirect : AbstractOperationServicePlugIn
    {
        public override void BeginOperationTransaction(BeginOperationTransactionArgs e)
        {
            var obj = e.DataEntitys.FirstOrDefault();
            string formId = this.BusinessInfo.GetForm().Id;
            if (formId.EqualsIgnoreCase(KdFomId.SAL_OUTSTOCK.ToString()))
            {
                DynamicObjectCollection rows = obj[KdEntry.SAL_OUTSTOCKENTRY.ToString()] as DynamicObjectCollection;

                DynamicObject zzstock = obj["FZZSTOCK"] as DynamicObject;
                string zzNumber = zzstock == null ? "" : zzstock["number"].GetString();
                int zzstockId = zzstock == null ? 0 : Convert.ToInt32(zzstock["Id"]);

                //FFromOrg 要货事业部
                DynamicObject fromOrg = obj["FFromOrg"] as DynamicObject;
                int fromOrgId = fromOrg == null ? 0 : Convert.ToInt32(fromOrg["Id"]);
                string fromOrgNumber = fromOrg == null ? "" : fromOrg["Number"].ToString();
                string fromOrgName = fromOrg == null ? "" : fromOrg["name"].ToString();
                if (fromOrg == null) { return; }
                if (fromOrgId == 0) { return; }
                //要货仓库
                DynamicObject fromStock = obj["FFromStock"] as DynamicObject;
                int fromStockId = fromStock == null ? 0 : Convert.ToInt32(fromStock["Id"]);
                string fromStockName = fromStock == null ? "" : Convert.ToString(fromStock["Name"]);
                string fromStockNumber = fromStock == null ? "" : fromStock["number"].ToString();
                //发货组织
                DynamicObject StockOrgId = obj["StockOrgId"] as DynamicObject;
                string stockOrgNumber = StockOrgId == null ? "" : StockOrgId["Number"].ToString();
                int fhOrgId = StockOrgId == null ? 0 : Convert.ToInt32(StockOrgId["Id"]);
                //单据编号
                string billNo = obj["BillNo"].GetString();

                List<string> msgList = GetRowsInv(rows, fromOrgId, fromStockId, fromOrgName, fromStockName);
                if (msgList.Count > 0)
                {
                    string err = string.Join(", ", msgList) + ",不允许提交！";
                    IOperationResult operationResult = GetInvInfos(err);
                    this.OperationResult.MergeResult(operationResult);
                    e.CancelOperation = true;
                    return;
                }
                if (fromOrg != null)
                {
                    if (fromStock == null)
                    {
                        throw new Exception("填了要货事业部，必须填要货仓库！");
                    }
                    if (fromOrgId == 1)
                    {
                        string err = "";
                        bool isZok = FromZ(fromOrgNumber, fromStockNumber, rows, stockOrgNumber, out err, fromOrgId, fromStockId, billNo);
                        if (!isZok)
                        {
                            //IOperationResult operationResult = GetZInfos(err);
                            //this.OperationResult.MergeResult(operationResult);
                            e.CancelOperation = true;
                            throw new Exception("从总部调拨不成功：" + err);
                        }
                        else
                        {
                            IOperationResult operationResult = GetZInfosOK(err);
                            this.OperationResult.MergeResult(operationResult);
                        }
                    }
                    else
                    {
                        if (fromOrgId == fhOrgId)
                        {
                            throw new Exception("要货事业部和发货组织一样，不可以跨组织调拨！");
                        }
                        List<Dictionary<int, string>> dicList = new List<Dictionary<int, string>>();
                        List<Dictionary<int, string>> srcStockList = new List<Dictionary<int, string>>();
                        bool isFromA = FromA(fromOrgNumber, fromStockNumber, rows, stockOrgNumber, fromOrgId, this.OperationResult, out dicList, out srcStockList, billNo);
                        if (isFromA)
                        {
                            string err = "";
                            bool isZok = FromAZ(fromOrgNumber, fromStockNumber, rows, stockOrgNumber, out err, fromOrgId, dicList, srcStockList, billNo, zzNumber, zzstockId, zzstock);
                            if (!isZok)
                            {
                                IOperationResult operationResult = GetZInfos(err);
                                this.OperationResult.MergeResult(operationResult);
                                e.CancelOperation = true;
                                throw new Exception("从事业部调拨失败：" + err);
                            }
                            else
                            {
                                IOperationResult operationResult = GetZInfosOK(err);
                                this.OperationResult.MergeResult(operationResult);
                            }
                        }
                        else
                        {
                            e.CancelOperation = true;
                            return;
                        }
                    }
                }
            }
            base.BeginOperationTransaction(e);
        }
        public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
        {
            base.AfterExecuteOperationTransaction(e);
            var obj = e.DataEntitys.FirstOrDefault();
            string formId = this.BusinessInfo.GetForm().Id;
            if (formId.EqualsIgnoreCase(KdFomId.SAL_RETURNSTOCK.ToString()))
            {
                //
                DynamicObject FZZSTOCK = obj["FZZSTOCK"] as DynamicObject;
                string zzNumber = FZZSTOCK == null ? "" : FZZSTOCK["number"].GetString();
                int zzStockId = FZZSTOCK == null ? 0 : Convert.ToInt32(FZZSTOCK["Id"]);
                //单据编号
                string billNo = obj["BillNo"].GetString();
                //FFromOrg 退货事业部
                DynamicObject decOrg = obj["FDecOrg"] as DynamicObject;
                //FFromOrg 退货仓库
                DynamicObject decStock = obj["FDecStock"] as DynamicObject;
                string decStockNumber = decStock == null ? "" : decStock["number"].ToString();
                int decStockId = decStock == null ? 0 : Convert.ToInt32(decStock["Id"]);
                //销售退货单库存组织
                DynamicObject stockOrg = obj["StockOrgId"] as DynamicObject;
                int stockOrgId = stockOrg == null ? 0 : Convert.ToInt32(stockOrg["Id"]);
                if (decOrg == null) { return; }
                if (decOrg != null && decStock == null)
                {
                    throw new Exception("填了退货货事业部，必须填退货仓库！");
                }
                int decOrgId = decOrg == null ? 0 : Convert.ToInt32(decOrg["Id"]);
                string decOrgNumber = decOrg == null ? "" : decOrg["Number"].ToString();
                DynamicObjectCollection rows = obj[KdEntry.SAL_RETURNSTOCKENTRY.ToString()] as DynamicObjectCollection;
                if (decOrgId == 1)
                {
                    string msg = "";
                    List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
                    List<Dictionary<int, string>> srcLoc = new List<Dictionary<int, string>>();
                    bool isDecZ = DecA2Z(rows, stockOrgId, this.OperationResult, out msg, out srcStock, out srcLoc, billNo);
                    if (!isDecZ)
                    {
                        throw new Exception("退货失败：" + msg);
                    }
                }
                else
                {
                    if (decOrgId == stockOrgId)
                    {
                        throw new Exception("退货事业部和库存组织一样，不可以跨组织调拨！");
                    }
                    string msg = "";
                    List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
                    List<Dictionary<int, string>> srcLoc = new List<Dictionary<int, string>>();
                    bool isDecZ = DecA2Z(rows, stockOrgId, this.OperationResult, out msg, out srcStock, out srcLoc, billNo);
                    if (isDecZ)
                    {
                        bool isDecZB = DecZ2B(decOrgNumber, decStockNumber, rows, stockOrgId, out msg, srcStock, srcLoc, decStockId, billNo, zzNumber, zzStockId);
                        if (!isDecZB)
                        {
                            throw new Exception("退货失败：" + msg);
                        }
                        else
                        {
                            IOperationResult operationResult = GetZInfosOK(msg);
                            this.OperationResult.MergeResult(operationResult);
                        }
                    }
                    else
                    {
                        throw new Exception("退货失败：" + msg);
                    }
                }
            }
        }
        //public override void EndOperationTransaction(EndOperationTransactionArgs e)
        //{
        //    var obj = e.DataEntitys.FirstOrDefault();
        //    string formId = this.BusinessInfo.GetForm().Id;
        //    if (formId.EqualsIgnoreCase(KdFomId.SAL_RETURNSTOCK.ToString()))
        //    {
        //        //FFromOrg 退货事业部
        //        DynamicObject decOrg = obj["FDecOrg"] as DynamicObject;
        //        //FFromOrg 退货仓库
        //        DynamicObject decStock = obj["FDecStock"] as DynamicObject;
        //        string decStockNumber = decStock == null ? "" : decStock["number"].ToString();
        //        int decStockId = decStock == null ? 0 : Convert.ToInt32(decStock["Id"]);
        //        //销售退货单库存组织
        //        DynamicObject stockOrg = obj["StockOrgId"] as DynamicObject;
        //        int stockOrgId = stockOrg == null ? 0 : Convert.ToInt32(stockOrg["Id"]);
        //        if (decOrg == null) { return; }
        //        if (decOrg != null && decStock == null)
        //        {
        //            throw new Exception("填了退货货事业部，必须填退货仓库！");
        //        }
        //        int decOrgId = decOrg == null ? 0 : Convert.ToInt32(decOrg["Id"]);
        //        string decOrgNumber = decOrg == null ? "" : decOrg["Number"].ToString();
        //        DynamicObjectCollection rows = obj[KdEntry.SAL_RETURNSTOCKENTRY.ToString()] as DynamicObjectCollection;
        //        if (decOrgId == 1)
        //        {
        //            string msg = "";
        //            List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
        //            List<Dictionary<int, string>> srcLoc = new List<Dictionary<int, string>>();
        //            bool isDecZ = DecA2Z(rows, stockOrgId, this.OperationResult, out msg, out srcStock, out srcLoc);
        //            if (!isDecZ)
        //            {
        //                throw new Exception("退货失败：" + msg);
        //            }
        //        }
        //        else
        //        {
        //            if (decOrgId == stockOrgId)
        //            {
        //                throw new Exception("退货事业部和库存组织一样，不可以跨组织调拨！");
        //            }
        //            string msg = "";
        //            List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
        //            List<Dictionary<int, string>> srcLoc = new List<Dictionary<int, string>>();
        //            bool isDecZ = DecA2Z(rows, stockOrgId, this.OperationResult, out msg, out srcStock, out srcLoc);
        //            if (isDecZ)
        //            {
        //                bool isDecZB = DecZ2B(decOrgNumber, decStockNumber, rows, stockOrgId, out msg, srcStock, srcLoc, decStockId);
        //                if (!isDecZB)
        //                {
        //                    throw new Exception("退货失败：" + msg);
        //                }
        //                else
        //                {
        //                    IOperationResult operationResult = GetZInfosOK(msg);
        //                    this.OperationResult.MergeResult(operationResult);
        //                }
        //            }
        //            else
        //            {
        //                throw new Exception("退货失败：" + msg);
        //            }
        //        }
        //    }
        //    base.EndOperationTransaction(e);
        //}

        private bool DecZ2B(string decOrgNumber, string decStockNumber, DynamicObjectCollection rows, int stockOrgId, out string err, List<Dictionary<int, string>> srcStock, List<Dictionary<int, string>> srcLoc, int decStockId, string billNo, string zzNumber, int zzStockId)
        {
            string z2bJson = GetZ2BJson(decOrgNumber, decStockNumber, rows, stockOrgId, srcStock, srcLoc, decStockId, billNo, zzNumber, zzStockId);
            string formId = KdFomId.STK_TransferDirect.ToString();
            var apiResult = KDApi.Save(this.Context, formId, z2bJson);
            List<string> errList = new List<string>();
            err = "";
            if (apiResult.Result.ResponseStatus.IsSuccess)
            {
                errList.Add(apiResult.Result.Number.ToString());
                err = string.Join(",", errList);
                return true;
            }
            else
            {
                if (apiResult.Result.ResponseStatus.Errors.Count > 0)
                {
                    foreach (var mes in apiResult.Result.ResponseStatus.Errors)
                    {
                        errList.Add(mes.Message);
                    }
                }
                err = string.Join(",", errList);
                return false;
            }
        }

        private string GetZ2BJson(string stockOrgNumber, string decStockNumber, DynamicObjectCollection rows, int stockOrgId, List<Dictionary<int, string>> srcStock, List<Dictionary<int, string>> srcLoc, int decStockId, string billNo, string zzNumber, int zzStockId)
        {
            string fromStockNumber = zzNumber;//CK003
            string srcLocNumber = GetLocSrcNumber(zzStockId);
            string decLocNumber = GetDecLocNumber(decStockId);
            string fromOrgNumber = GetZOrgNumber(1);
            TransferDirect model = new TransferDirect();
            model.IsAutoSubmitAndAudit = true;
            model.Model = new TransferDirectModel()
            {
                FBillTypeID = new GetNumber() { FNumber = "ZJDB01_SYS" },
                FBizType = "NORMAL",
                FTransferDirect = "GENERAL",
                FTransferBizType = "OverOrgTransfer",
                FTransferBizTypeId = new GetNumber() { FNumber = "OverOrgTransfer" },
                FSettleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FSaleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FStockOutOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FOwnerTypeOutIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerOutIdHead = new GetNumber() { FNumber = fromOrgNumber },
                FStockOrgId = new GetNumber() { FNumber = stockOrgNumber },
                FIsIncludedTax = true,
                FIsPriceExcludeTax = true,
                FExchangeTypeId = new GetNumber() { FNumber = "HLTX01_SYS" },
                FOwnerTypeIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerIdHead = new GetNumber() { FNumber = stockOrgNumber },
                FDate = DateTime.Now.ToString(),
                FNote = "销售出库单提交自动创建",
                FTrBillNo = billNo,
                FBillEntry = new List<FBillEntryItem>(),
            };
            foreach (var row in rows)
            {
                DynamicObject mat = row["MaterialID"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                int id = Convert.ToInt32(row["id"]);
                //string fromStockNumber = GetStockNumber(srcStock, id);
                //string srcLocNumber = GetLocSrcNumber(srcLoc, id);
                DynamicObject unt = row["UnitID"] as DynamicObject;
                decimal qty = Convert.ToDecimal(row["RealQty"]);
                DynamicObject StockID = row["StockID"] as DynamicObject;

                DynamicObject auxProp = row["AuxPropId"] as DynamicObject;
                int auxId = auxProp == null ? 0 : Convert.ToInt32(auxProp["Id"]);
                DynamicObject f10002 = auxProp["F100001"] as DynamicObject;
                string auxNumber = f10002 == null ? "" : f10002["fnumber"].GetString();

                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();

                FBillEntryItem rowItem = new FBillEntryItem()
                {
                    FMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() },
                    FAuxPropId = new FAuxPropId() { FAUXPROPID__FF100001 = new GetNumber() { FNumber = auxNumber } },
                    FUnitID = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FQty = qty,
                    FLot = new GetNumber() { FNumber = lotNumber },
                    FSrcStockId = new GetNumber() { FNumber = fromStockNumber },
                    FSrcStockLocId = new FSrcStockLocId() { FSRCSTOCKLOCID__FF100002 = new GetNumber() { FNumber = srcLocNumber } },
                    FDestStockId = new GetNumber() { FNumber = decStockNumber },
                    FDestStockLocId = new FDestStockLocId() { FDESTSTOCKLOCID__FF100002 = new GetNumber() { FNumber = decLocNumber } },
                    FSrcStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FDestStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FOwnerTypeOutId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FOwnerTypeId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerId = new GetNumber() { FNumber = stockOrgNumber },
                    FBaseUnitId = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FBaseQty = qty,
                    FKeeperTypeId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperId = new GetNumber() { FNumber = stockOrgNumber },
                    FKeeperTypeOutId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FDestMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() }
                };
                model.Model.FBillEntry.Add(rowItem);
            }
            string json = JsonConvert.SerializeObject(model);
            return json;
        }

        private string GetDecLocNumber(int decStockId)
        {
            var res = KDApi.ExecuteBillQuery(this.Context, KdFomId.BD_STOCK.ToString(), "FFlexEntryId.FNUMBER", $"FSTOCKID={decStockId}", "FFlexEntryId.FNUMBER", 1);
            if (res.Count > 0)
            {
                return res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return "";
        }

        private string GetLocSrcNumber(int zzStockId)
        {
            var res = KDApi.ExecuteBillQuery(this.Context, KdFomId.BD_STOCK.ToString(), "FFlexEntryId.FNUMBER", $"FSTOCKID={zzStockId}", "FFlexEntryId.FNUMBER", 1);
            if (res.Count > 0)
            {
                return res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return "";
        }

        private string GetStockNumber(List<Dictionary<int, string>> srcStock, int id)
        {
            foreach (var src in srcStock)
            {
                if (src.Keys.First() == id)
                {
                    return src.Values.FirstOrDefault();
                }
            }
            return "";
        }

        private bool DecA2Z(DynamicObjectCollection rows, int stockOrgId, IOperationResult operationResult, out string msg, out List<Dictionary<int, string>> srcStock, out List<Dictionary<int, string>> srcLoc, string billNo)
        {
            srcStock = new List<Dictionary<int, string>>();
            srcLoc = new List<Dictionary<int, string>>();
            msg = "";
            string formId = KdFomId.STK_TransferDirect.ToString();
            List<DynamicObject> listObj = new List<DynamicObject>();
            List<Dictionary<string, decimal>> dics = new List<Dictionary<string, decimal>>();
            foreach (var row in rows)
            {
                DynamicObject mat = row["MaterialId"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                decimal v = Convert.ToDecimal(row["RealQty"]);
                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                //string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();
                int lotId = lotObj == null ? 0 : Convert.ToInt32(lotObj["id"]);
                DynamicObjectCollection seleList = GetSeleList(this.Context, 1, stockOrgId, matNumber, lotId);
                if (seleList.Count > 0)
                {
                    foreach (var sel in seleList)
                    {
                        string eId = sel["FENTRYID"].ToString();
                        decimal qty = Convert.ToDecimal(sel["FBASEQTY"]);
                        decimal checkQty = 0;
                        if (qty < v)
                        {
                            checkQty = qty;
                        }
                        else
                        {
                            checkQty = v;
                        }
                        var dic = new Dictionary<string, decimal>();
                        dic.Add(eId, checkQty);
                        dics.Add(dic);
                        v = v - qty;
                        if (v <= 0)
                        {
                            break;
                        }
                    }
                }
            }
            if (dics.Count > 0)
            {
                List<string> list = new List<string>();
                foreach (var dic in dics)
                {
                    list.Add(dic.Keys.FirstOrDefault());
                }
                string ids = string.Join(",", list);
                var res = KingdeeTools.DzConvertServiceList(this.Context, formId, formId, "FBillEntry", "", "", "", list, "TransferDirect-TransferDirect");
                var tObj = AfterAllPush(res, dics, billNo, formId);
                listObj.AddRange(tObj);
            }
            FormMetadata meta = (FormMetadata)AppServiceContext.MetadataService.Load(this.Context, formId, true);
            OperateOption option = OperateOption.Create();
            operationResult.MergeResult(AppServiceContext.SaveService.Save(this.Context, meta.BusinessInfo, listObj.ToArray(), option, ""));
            if (operationResult.IsSuccess)
            {
                var array = (from o in listObj
                             select o["Id"]).ToArray();
                operationResult.MergeResult(AppServiceContext.SubmitService.Submit(this.Context, meta.BusinessInfo, array, "Submit", null));
                if (operationResult.IsSuccess)
                {
                    var audit = AppServiceContext.AuditService.Audit(this.Context, meta.BusinessInfo, array, OperateOption.Create());
                    if (audit.IsSuccess)
                    {
                        operationResult.MergeResult(audit);
                    }
                    else
                    {
                        msg = audit.InteractionContext.SimpleMessage;
                        return false;
                    }
                }
            }
            var suObjs = operationResult.OperateResult;
            var erRes = suObjs.GetFailResult();
            var ereCount = erRes.Count();
            if (ereCount > 0)
            {
                return false;
            }
            return true;
        }

        private IEnumerable<DynamicObject> AfterAllPush(ConvertOperationResult res, List<Dictionary<string, decimal>> dics, string billNo, string formId)
        {
            if (!res.IsSuccess)
            {
                return null;
            }
            var array = res.TargetDataEntities.ToArray();
            List<DynamicObject> list = new List<DynamicObject>();
            foreach (var extData in array)
            {
                IBillView val = KingdeeTools.CreateBillView(this.Context, formId);
                val.Model.DataObject = extData.DataEntity;
                val.Model.DataObject["Note"] = "销售出库单提交自动创建";
                val.Model.DataObject["FTrBillNo"] = billNo;
                RelatedFlexGroupField stockLocField = val.BusinessInfo.GetField("FDestStockLocId") as RelatedFlexGroupField;
                DynamicObjectCollection rows = val.Model.DataObject["TransferDirectEntry"] as DynamicObjectCollection;
                for (int i = 0; i < rows.Count; i++)
                {
                    string srceid = rows[i]["FsrcEid"].ToString();
                    foreach (var dic in dics)
                    {
                        if (dic.Keys.FirstOrDefault() == srceid)
                        {
                            val.Model.SetValue("FQty", dic.Values.FirstOrDefault(), i);
                            val.Model.SetValue("FBaseQty", dic.Values.FirstOrDefault(), i);
                        }
                    }

                    DynamicObject dyRow = val.Model.GetEntityDataObject(stockLocField.Entity)[i];
                    // 清空仓位
                    stockLocField.DynamicProperty.SetValue(dyRow, null);
                    stockLocField.RefIDDynamicProperty.SetValue(dyRow, 0);

                    var stockLoc = BusinessDataServiceHelper.LoadFromCache(this.Context, new object[] { 100019 }, stockLocField.RefFormDynamicObjectType);
                    stockLocField.DynamicProperty.SetValue(dyRow, stockLoc[0]);
                    stockLocField.RefIDDynamicProperty.SetValue(dyRow, 100019);
                }
                list.Add(val.Model.DataObject);
            }
            return list;
        }

        private List<Dictionary<int, string>> GetSrcLoc(int id, ConvertOperationResult res)
        {
            List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
            foreach (var t in res.TargetDataEntities)
            {
                var trObj = t.DataEntity;
                DynamicObjectCollection trows = trObj["TransferDirectEntry"] as DynamicObjectCollection;
                foreach (var trow in trows)
                {
                    DynamicObject stockLoc = trow["DestStockLocId"] as DynamicObject;
                    var f100001 = stockLoc["F100002"] as DynamicObject;
                    string stockLocNumber = f100001 == null ? "" : f100001["number"].GetString();
                    //DynamicObject stockObj = trow["DestStockLocId"] as DynamicObject;
                    //string srcStockNumber = stockObj == null ? "" : stockObj["number"].ToString();
                    Dictionary<int, string> dic = new Dictionary<int, string>();
                    dic.Add(id, stockLocNumber);
                    srcStock.Add(dic);
                }
            }
            return srcStock;
        }

        private List<Dictionary<int, string>> GetSrcStock(int id, ConvertOperationResult res)
        {
            List<Dictionary<int, string>> srcStock = new List<Dictionary<int, string>>();
            foreach (var t in res.TargetDataEntities)
            {
                var trObj = t.DataEntity;
                DynamicObjectCollection trows = trObj["TransferDirectEntry"] as DynamicObjectCollection;
                foreach (var trow in trows)
                {
                    DynamicObject stockObj = trow["DestStockId"] as DynamicObject;
                    string srcStockNumber = stockObj == null ? "" : stockObj["number"].ToString();
                    Dictionary<int, string> dic = new Dictionary<int, string>();
                    dic.Add(id, srcStockNumber);
                    srcStock.Add(dic);
                }
            }
            return srcStock;
        }

        private bool FromAZ(string fromOrgNumber, string fromStockNumber, DynamicObjectCollection rows, string stockOrgNumber, out string err, int fromOrgId, List<Dictionary<int, string>> dicList, List<Dictionary<int, string>> srcStockList, string billNo, string zzNumber, int zzstockId, DynamicObject zzstock)
        {
            string tranJson = GetAZJson(fromOrgNumber, fromStockNumber, rows, stockOrgNumber, fromOrgId, dicList, srcStockList, billNo, zzNumber, zzstockId, zzstock);
            //调用接口，创建直接调拨单
            string formId = KdFomId.STK_TransferDirect.ToString();
            var apiResult = KDApi.Save(this.Context, formId, tranJson);
            List<string> errList = new List<string>();
            err = "";
            if (apiResult.Result.ResponseStatus.IsSuccess)
            {
                errList.Add(apiResult.Result.Number.ToString());
                err = string.Join(",", errList);
                return true;
            }
            else
            {
                if (apiResult.Result.ResponseStatus.Errors.Count > 0)
                {
                    foreach (var mes in apiResult.Result.ResponseStatus.Errors)
                    {
                        errList.Add(mes.Message);
                    }
                }
                err = string.Join(",", errList);
                return false;
            }
        }

        private string GetAZJson(string fromOrgNumber, string fromStockNumber, DynamicObjectCollection rows, string stockOrgNumber, int fromOrgId, List<Dictionary<int, string>> dicList, List<Dictionary<int, string>> srcStockList, string billNo, string zzNumber, int zzstockId, DynamicObject zzstock)
        {
            string srcLocNumber = GetSumbitLoc(zzstockId);
            fromOrgNumber = GetZOrgNumber(1);
            TransferDirect model = new TransferDirect();
            model.IsAutoSubmitAndAudit = true;
            model.Model = new TransferDirectModel()
            {
                FBillTypeID = new GetNumber() { FNumber = "ZJDB01_SYS" },
                FBizType = "NORMAL",
                FTransferDirect = "GENERAL",
                FTransferBizType = "OverOrgTransfer",
                FTransferBizTypeId = new GetNumber() { FNumber = "OverOrgTransfer" },
                FSettleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FSaleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FStockOutOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FOwnerTypeOutIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerOutIdHead = new GetNumber() { FNumber = fromOrgNumber },
                FStockOrgId = new GetNumber() { FNumber = stockOrgNumber },
                FIsIncludedTax = true,
                FIsPriceExcludeTax = true,
                FExchangeTypeId = new GetNumber() { FNumber = "HLTX01_SYS" },
                FOwnerTypeIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerIdHead = new GetNumber() { FNumber = stockOrgNumber },
                FDate = DateTime.Now.ToString(),
                FNote = "销售出库单提交自动创建",
                FTrBillNo = billNo,
                FBillEntry = new List<FBillEntryItem>(),
            };
            foreach (var row in rows)
            {
                DynamicObject mat = row["MaterialID"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                fromStockNumber = GetNewFromStockNumber(row, srcStockList);
                DynamicObject unt = row["UnitID"] as DynamicObject;
                decimal qty = Convert.ToDecimal(row["RealQty"]);
                DynamicObject StockID = row["StockID"] as DynamicObject;

                DynamicObject auxProp = row["AuxPropId"] as DynamicObject;
                int auxId = auxProp == null ? 0 : Convert.ToInt32(auxProp["Id"]);
                DynamicObject f10002 = auxProp["F100001"] as DynamicObject;
                string auxNumber = f10002 == null ? "" : f10002["fnumber"].GetString();

                DynamicObject stockLoc = row["StockLocID"] as DynamicObject;
                var f100001 = stockLoc == null ? null : stockLoc["F100002"] as DynamicObject;
                string stockLocNumber = f100001 == null ? "" : f100001["number"].GetString();
                string stockLocName = f100001 == null ? "" : f100001["name"].ToString();

                //string srcLocNumber = GetSrcLocNumber(row, dicList);

                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();

                FBillEntryItem rowItem = new FBillEntryItem()
                {
                    FMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() },
                    FAuxPropId = new FAuxPropId() { FAUXPROPID__FF100001 = new GetNumber() { FNumber = auxNumber } },
                    FUnitID = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FQty = qty,
                    FLot = new GetNumber() { FNumber = lotNumber },
                    FSrcStockId = new GetNumber() { FNumber = zzNumber },
                    FSrcStockLocId = new FSrcStockLocId() { FSRCSTOCKLOCID__FF100002 = new GetNumber() { FNumber = srcLocNumber } },
                    FDestStockId = new GetNumber() { FNumber = StockID == null ? "" : StockID["number"].ToString() },
                    FDestStockLocId = new FDestStockLocId() { FDESTSTOCKLOCID__FF100002 = new GetNumber() { FNumber = stockLocNumber } },
                    FSrcStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FDestStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FOwnerTypeOutId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FOwnerTypeId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerId = new GetNumber() { FNumber = stockOrgNumber },
                    FBaseUnitId = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FBaseQty = qty,
                    FKeeperTypeId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperId = new GetNumber() { FNumber = stockOrgNumber },
                    FKeeperTypeOutId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FDestMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() }
                };
                model.Model.FBillEntry.Add(rowItem);
            }
            string json = JsonConvert.SerializeObject(model);
            return json;
        }

        private string GetSumbitLoc(int zzstockId)
        {
            var res = KDApi.ExecuteBillQuery(this.Context, KdFomId.BD_STOCK.ToString(), "FFlexEntryId.FNUMBER", $"FSTOCKID={zzstockId}", "FFlexEntryId.FNUMBER", 1);
            if (res.Count > 0)
            {
                return res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return "";
        }

        private string GetNewFromStockNumber(DynamicObject row, List<Dictionary<int, string>> srcStockList)
        {
            int id = Convert.ToInt32(row["Id"]);
            foreach (var dic in srcStockList)
            {
                if (dic.Keys.First() == id)
                {
                    return dic.Values.FirstOrDefault();
                }
            }
            return "";
        }

        private string GetSrcLocNumber(DynamicObject row, List<Dictionary<int, string>> dicList)
        {
            int id = Convert.ToInt32(row["Id"]);
            foreach (var dic in dicList)
            {
                if (dic.Keys.First() == id)
                {
                    return dic.Values.FirstOrDefault();
                }
            }
            return "";
        }

        private string GetFromStockNumber(int v, int fromOrgId, string matNumber)
        {
            int matId = GetMatId(this.Context, matNumber, fromOrgId);
            string sql = string.Format(@"/*dialect*/ 
            SELECT T3.FNUMBER
            FROM T_STK_STKTRANSFERIN T0
                 JOIN T_STK_STKTRANSFERINENTRY T1 ON T1.FID = T0.FID
                 JOIN T_STK_STKTRANSFERINENTRY_R T2 ON T2.FENTRYID = T1.FENTRYID
                 JOIN T_BD_STOCK T3 ON T3.FSTOCKID = T1.FSRCSTOCKID
            WHERE T0.FSTOCKOUTORGID = {0}
                  AND T0.FSTOCKORGID = {1}
                  AND T0.FVESTONWAY = 'Dest'
                  AND T0.FDOCUMENTSTATUS = 'C'
                  AND T1.FMATERIALID = {2}
                  AND (T1.FBASEQTY - T2.FBASEJOINQTY) > 0 
            ORDER BY T0.FDATE ", v, fromOrgId, matId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(this.Context, sql);
            if (doc.Count > 0)
            {
                return doc[0]["FNUMBER"].ToString();
            }
            return "";
        }

        private string GetZOrgNumber(int v)
        {
            var res = KDApi.ExecuteBillQuery(this.Context, KdFomId.ORG_Organizations.ToString(), "fnumber", $"forgid={v}", "fnumber", 1);
            if (res.Count > 0)
            {
                return res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return "";
        }

        private bool FromA(string fromOrgNumber, string fromStockNumber, DynamicObjectCollection rows, string stockOrgNumber, int fromOrgId, IOperationResult operationResult, out List<Dictionary<int, string>> dicList, out List<Dictionary<int, string>> srcStockList, string billNo)
        {
            string formId = KdFomId.STK_TransferDirect.ToString();
            //err = "";
            FormMetadata meta = (FormMetadata)AppServiceContext.MetadataService.Load(this.Context, formId, true);
            OperateOption option = OperateOption.Create();
            List<DynamicObject> listObj = new List<DynamicObject>();
            dicList = new List<Dictionary<int, string>>();
            srcStockList = new List<Dictionary<int, string>>();
            List<Dictionary<string, decimal>> dics = new List<Dictionary<string, decimal>>();
            foreach (var row in rows)
            {
                DynamicObject mat = row["MaterialID"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                decimal v = Convert.ToDecimal(row["RealQty"]);
                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                //string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();
                int lotId = lotObj == null ? 0 : Convert.ToInt32(lotObj["id"]);
                DynamicObjectCollection seleList = GetSeleList(this.Context, 1, fromOrgId, matNumber, lotId);
                if (seleList.Count > 0)
                {
                    foreach (var sel in seleList)
                    {
                        string eId = sel["FENTRYID"].ToString();
                        decimal qty = Convert.ToDecimal(sel["FBASEQTY"]);
                        decimal checkQty = 0;
                        if (qty < v)
                        {
                            checkQty = qty;
                        }
                        else
                        {
                            checkQty = v;
                        }
                        var dic = new Dictionary<string, decimal>();
                        dic.Add(eId, checkQty);
                        dics.Add(dic);
                        v = v - qty;
                        if (v <= 0)
                        {
                            break;
                        }
                    }
                }
            }
            if (dics.Count > 0)
            {
                List<string> list = new List<string>();
                foreach (var dic in dics)
                {
                    list.Add(dic.Keys.FirstOrDefault());
                }
                string ids = string.Join(",", list);
                var res = KingdeeTools.DzConvertServiceList(this.Context, formId, formId, "FBillEntry", "", "", "", list, "TransferDirect-TransferDirect");
                var tObj = AfterAllSalPush(res, dics, billNo, formId);
                listObj.AddRange(tObj);
            }
            operationResult.MergeResult(AppServiceContext.SaveService.Save(this.Context, meta.BusinessInfo, listObj.ToArray(), option, ""));
            if (operationResult.IsSuccess)
            {
                var array = (from o in listObj
                             select o["Id"]).ToArray();
                operationResult.MergeResult(AppServiceContext.SubmitService.Submit(this.Context, meta.BusinessInfo, array, "Submit", null));
                if (operationResult.IsSuccess)
                {
                    operationResult.MergeResult(AppServiceContext.AuditService.Audit(this.Context, meta.BusinessInfo, array, OperateOption.Create()));
                }
            }
            var suObjs = operationResult.OperateResult;
            var erRes = suObjs.GetFailResult();
            var ereCount = erRes.Count();
            if (ereCount > 0)
            {
                return false;
            }
            return true;
        }

        private IEnumerable<DynamicObject> AfterAllSalPush(ConvertOperationResult res, List<Dictionary<string, decimal>> dics, string billNo, string formId)
        {
            if (!res.IsSuccess)
            {
                return null;
            }
            var array = res.TargetDataEntities.ToArray();
            List<DynamicObject> list = new List<DynamicObject>();
            foreach (var extData in array)
            {
                IBillView val = KingdeeTools.CreateBillView(this.Context, formId);
                val.Model.DataObject = extData.DataEntity;
                val.Model.DataObject["Note"] = "销售出库单提交自动创建";
                val.Model.DataObject["FTrBillNo"] = billNo;
                //RelatedFlexGroupField val5 = val.BusinessInfo.GetField("FDestStockLocId") as RelatedFlexGroupField;
                RelatedFlexGroupField stockLocField = val.BusinessInfo.GetField("FDestStockLocId") as RelatedFlexGroupField;
                DynamicObjectCollection rows = val.Model.DataObject["TransferDirectEntry"] as DynamicObjectCollection;
                for (int i = 0; i < rows.Count; i++)
                {
                    string srceid = rows[i]["FsrcEid"].ToString();
                    foreach (var dic in dics)
                    {
                        if (dic.Keys.FirstOrDefault() == srceid)
                        {
                            val.Model.SetValue("FQty", dic.Values.FirstOrDefault(), i);
                            val.Model.SetValue("FBaseQty", dic.Values.FirstOrDefault(), i);
                        }
                    }

                    DynamicObject dyRow = val.Model.GetEntityDataObject(stockLocField.Entity)[i];
                    // 清空仓位
                    stockLocField.DynamicProperty.SetValue(dyRow, null);
                    stockLocField.RefIDDynamicProperty.SetValue(dyRow, 0);

                    var stockLoc = BusinessDataServiceHelper.LoadFromCache(this.Context, new object[] { 100019 }, stockLocField.RefFormDynamicObjectType);
                    stockLocField.DynamicProperty.SetValue(dyRow, stockLoc[0]);
                    stockLocField.RefIDDynamicProperty.SetValue(dyRow, 100019);
                }
                list.Add(val.Model.DataObject);
            }
            return list;
        }

        private List<DynamicObject> AfterPush(ConvertOperationResult res, decimal checkQty, string billNo)
        {
            if (!res.IsSuccess)
            {
                return null;
            }
            var array = res.TargetDataEntities.ToArray();
            List<DynamicObject> list = new List<DynamicObject>();
            foreach (var extData in array)
            {
                DynamicObject dataEntity = extData.DataEntity;
                dataEntity["Note"] = "销售出库单提交自动创建";
                dataEntity["FTrBillNo"] = billNo;
                DynamicObjectCollection rows = dataEntity["TransferDirectEntry"] as DynamicObjectCollection;
                foreach (var row in rows)
                {
                    row["Qty"] = checkQty;
                    row["BaseQty"] = checkQty;
                }
                list.Add(dataEntity);
            }
            return list;
        }

        private DynamicObjectCollection GetSeleList(Context ctx, int outOrgId, int fromOrgId, string matNumber, int lotId)
        {
            //int outOrgId = outOrg == null ? 1 : Convert.ToInt32(outOrg["Id"]);
            //int fromOrgId = fromOrg == null ? 0 : Convert.ToInt32(fromOrg["Id"]);
            int matId = GetMatId(ctx, matNumber, fromOrgId);
            string sql = string.Format(@"/*dialect*/ 
            SELECT T0.FID, 
                   T1.FENTRYID, 
                   T1.FBASEQTY - T2.FBASEJOINQTY FBASEQTY,T3.FNUMBER
            FROM T_STK_STKTRANSFERIN T0
                 JOIN T_STK_STKTRANSFERINENTRY T1 ON T1.FID = T0.FID
                 JOIN T_STK_STKTRANSFERINENTRY_R T2 ON T2.FENTRYID = T1.FENTRYID
                 JOIN T_BD_STOCK T3 ON T3.FSTOCKID = T1.FSRCSTOCKID
            WHERE T0.FSTOCKOUTORGID = {0}
                  AND T0.FSTOCKORGID = {1}
                  AND T0.FVESTONWAY = 'Dest'
                  AND T0.FDOCUMENTSTATUS = 'C'
                  AND T1.FMATERIALID = {2}
                  AND (T1.FBASEQTY - T2.FBASEJOINQTY) > 0 AND T1.FLOT={3}
            ORDER BY (T1.FBASEQTY - T2.FBASEJOINQTY) DESC,T0.FDATE ", outOrgId, fromOrgId, matId, lotId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(ctx, sql);
            return doc;
        }

        private int GetMatId(Context ctx, string matNumber, int fromOrgId)
        {
            string sql = string.Format(@"/*dialect*/ 
            SELECT FMATERIALID FROM T_BD_MATERIAL WHERE FNUMBER='{0}' AND FUSEORGID={1} ", matNumber, fromOrgId);
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(ctx, sql);
            if (doc.Count > 0)
            {
                return Convert.ToInt32(doc[0][0]);
            }
            else
            {
                return 0;
            }
        }

        private IOperationResult GetInvInfos(string err)
        {
            IOperationResult operationResult = new OperationResult();
            operationResult.OperateResult = new OperateResultCollection()
            {
                new OperateResult()
                {
                    SuccessStatus = false,
                    Message = "库存校验："+err,
                    MessageType = MessageType.FatalError,
                    Name = "库存校验",
                    PKValue = 0
                }
            };
            return operationResult;
        }

        private List<string> GetRowsInv(DynamicObjectCollection rows, int fromOrgId, int fromStockId, string fromOrgName, string fromStockName)
        {
            List<string> result = new List<string>();
            int i = 1;
            foreach (var row in rows)
            {
                DynamicObject stockLoc = row["StockLocID"] as DynamicObject;
                var f100001 = stockLoc["F100002"] as DynamicObject;
                string stockLocNumber = f100001 == null ? "" : f100001["number"].GetString();
                string stockLocName = f100001 == null ? "" : f100001["name"].ToString();
                DynamicObject auxProp = row["AuxPropId"] as DynamicObject;
                int auxId = auxProp == null ? 0 : Convert.ToInt32(auxProp["Id"]);
                DynamicObject f10002 = auxProp["F100001"] as DynamicObject;
                string auxNumber = f10002 == null ? "" : f10002["fnumber"].GetString();
                string auxName = f10002 == null ? "" : f10002["FDataValue"].ToString();
                DynamicObject mat = row["MaterialID"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                //bool IsBatchManage = mat == null ? false : Convert.ToBoolean(mat["IsBatchManage"]);
                bool IsBatchManage = GetMatIsBatchManage(matNumber, fromOrgId);

                DynamicObjectCollection matBase = mat["MaterialBase"] as DynamicObjectCollection;
                var mbase = matBase.FirstOrDefault();
                int ErpClsID = Convert.ToInt32(mbase["ErpClsID"]);

                DynamicObject unt = row["UnitID"] as DynamicObject;
                decimal qty = Convert.ToDecimal(row["RealQty"]);
                string qtyStr = qty.ToString().TrimEnd('0').TrimEnd('.');
                DynamicObject StockID = row["StockID"] as DynamicObject;
                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();
                string filterString = "";
                if (IsBatchManage)
                {
                    filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={fromOrgId} and FStockId={fromStockId} AND FAUXPROPID={auxId} and flot.fnumber='{lotNumber}' ";
                }
                else
                {
                    filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={fromOrgId} and FStockId={fromStockId} AND FAUXPROPID={auxId} ";
                }
                //string filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={fromOrgId} and FStockId={fromStockId} AND FAUXPROPID={auxId} and flot.fnumber='{lotNumber}' ";
                var fromOrgInvQty = KDApi.ExecuteBillQuery(this.Context, "STK_Inventory", "FBaseQty", filterString, "FBaseQty", 2000).Sum(s => Convert.ToDecimal(s.FirstOrDefault()));

                if (fromOrgInvQty < qty)
                {
                    if (ErpClsID < 4)
                    {
                        string fromQtyStr = fromOrgInvQty.ToString().TrimEnd('0').TrimEnd('.');
                        string msg = $"第{i}行物料编码{matNumber}需求量{qtyStr}，{fromOrgName}的{fromStockName}辅助属性{auxName}批号{lotNumber}的库存{fromQtyStr}不足";
                        result.Add(msg);
                    }
                }
                i++;
            }
            return result;
        }

        private bool GetMatIsBatchManage(string matNumber, int fromOrgId)
        {
            var res = KDApi.ExecuteBillQuery(this.Context, "BD_MATERIAL", "FIsBatchManage", $"FNUMBER='{matNumber}' AND FUseOrgId={fromOrgId} ", "FIsBatchManage", 1);
            if (res != null && res.Count > 0)
            {
                return Convert.ToBoolean(res.FirstOrDefault().FirstOrDefault());
            }
            return false;
        }

        private IOperationResult GetZInfosOK(string err)
        {
            IOperationResult operationResult = new OperationResult();
            operationResult.OperateResult = new OperateResultCollection()
            {
                new OperateResult()
                {
                    SuccessStatus = true,
                    Message = "从总部调拨成功,单号："+err,
                    MessageType = MessageType.Normal,
                    Name = "总部调拨",
                    PKValue = 0
                }
            };
            return operationResult;
        }

        private IOperationResult GetZInfos(string err)
        {
            IOperationResult operationResult = new OperationResult();
            operationResult.OperateResult = new OperateResultCollection()
            {
                new OperateResult()
                {
                    SuccessStatus = false,
                    Message = "从总部调拨不成功,原因："+err,
                    MessageType = MessageType.FatalError,
                    Name = "总部调拨",
                    PKValue = 0
                }
            };
            return operationResult;
        }

        private bool FromZ(string fromOrgNumber, string fromStockNumber, DynamicObjectCollection rows, string stockOrgNumber, out string err, int fromOrgId, int fromStockId, string billNo)
        {
            string tranJson = GetTranJson(fromOrgNumber, fromStockNumber, rows, stockOrgNumber, fromOrgId, fromStockId, billNo);
            //调用接口，创建直接调拨单
            string formId = KdFomId.STK_TransferDirect.ToString();
            var apiResult = KDApi.Save(this.Context, formId, tranJson);
            List<string> errList = new List<string>();
            err = "";
            if (apiResult.Result.ResponseStatus.IsSuccess)
            {
                errList.Add(apiResult.Result.Number.ToString());
                err = string.Join(",", errList);
                return true;
            }
            else
            {
                if (apiResult.Result.ResponseStatus.Errors.Count > 0)
                {
                    foreach (var mes in apiResult.Result.ResponseStatus.Errors)
                    {
                        errList.Add(mes.Message);
                    }
                }
                err = string.Join(",", errList);
                return false;
            }
        }

        private string GetTranJson(string fromOrgNumber, string fromStockNumber, DynamicObjectCollection rows, string stockOrgNumber, int fromOrgId, int fromStockId, string billNo)
        {
            TransferDirect model = new TransferDirect();
            model.IsAutoSubmitAndAudit = true;
            model.Model = new TransferDirectModel()
            {
                FBillTypeID = new GetNumber() { FNumber = "ZJDB01_SYS" },
                FBizType = "NORMAL",
                FTransferDirect = "GENERAL",
                FTransferBizType = "OverOrgTransfer",
                FTransferBizTypeId = new GetNumber() { FNumber = "OverOrgTransfer" },
                FSettleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FSaleOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FStockOutOrgId = new GetNumber() { FNumber = fromOrgNumber },
                FOwnerTypeOutIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerOutIdHead = new GetNumber() { FNumber = fromOrgNumber },
                FStockOrgId = new GetNumber() { FNumber = stockOrgNumber },
                FIsIncludedTax = true,
                FIsPriceExcludeTax = true,
                FExchangeTypeId = new GetNumber() { FNumber = "HLTX01_SYS" },
                FOwnerTypeIdHead = KDOwnerType.BD_OwnerOrg.ToString(),
                FOwnerIdHead = new GetNumber() { FNumber = stockOrgNumber },
                FDate = DateTime.Now.ToString(),
                FNote = "销售出库单提交自动创建",
                FTrBillNo = billNo,
                FBillEntry = new List<FBillEntryItem>(),
            };
            foreach (var row in rows)
            {
                DynamicObject mat = row["MaterialID"] as DynamicObject;
                string matNumber = mat == null ? "" : mat["number"].ToString();
                DynamicObject unt = row["UnitID"] as DynamicObject;
                decimal qty = Convert.ToDecimal(row["RealQty"]);
                DynamicObject StockID = row["StockID"] as DynamicObject;

                DynamicObjectCollection matStock = mat["MaterialStock"] as DynamicObjectCollection;
                var mStock = matStock.FirstOrDefault();
                var StockPlaceId = mStock["StockPlaceId"] as DynamicObject;
                string stock100001Number = "";
                if (StockPlaceId == null)
                {
                    stock100001Number = "0001";
                }
                else
                {
                    var stock100001 = StockPlaceId == null ? null : StockPlaceId["f100002"] as DynamicObject;
                    stock100001Number = stock100001 == null ? "0001" : stock100001["number"].GetString();
                }


                DynamicObject auxProp = row["AuxPropId"] as DynamicObject;
                int auxId = auxProp == null ? 0 : Convert.ToInt32(auxProp["Id"]);
                DynamicObject f10002 = auxProp == null ? null : auxProp["F100001"] as DynamicObject;
                string auxNumber = f10002 == null ? "" : f10002["fnumber"].GetString();
                string auxName = f10002 == null ? "" : f10002["FDataValue"].ToString();
                string filterString = $"FMaterialId.fnumber='{matNumber}' and FStockOrgId={fromOrgId} and FStockId={fromStockId} AND FAUXPROPID={auxId} ";
                var srcStock = KDApi.ExecuteBillQuery(this.Context, "STK_Inventory", "FStockLocId.FF100002.FNUMBER", filterString, "FStockLocId.FF100002.FNUMBER", 1);
                string srcStockLocNumber = "";
                if (srcStock.Count > 0)
                {
                    if (srcStock.FirstOrDefault().FirstOrDefault() != null && srcStock != null)
                    {
                        srcStockLocNumber = srcStock.FirstOrDefault().FirstOrDefault().ToString();
                    }
                }
                else
                {
                    srcStockLocNumber = stock100001Number;
                }
                DynamicObject stockLoc = row["StockLocID"] as DynamicObject;
                var f100001 = stockLoc == null ? null : stockLoc["F100002"] as DynamicObject;
                string stockLocNumber = f100001 == null ? "" : f100001["number"].GetString();
                string stockLocName = f100001 == null ? "" : f100001["name"].ToString();
                //批号
                DynamicObject lotObj = row["lot"] as DynamicObject;
                string lotNumber = lotObj == null ? "" : lotObj["number"].ToString();
                FBillEntryItem rowItem = new FBillEntryItem()
                {
                    FMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() },
                    FAuxPropId = new FAuxPropId() { FAUXPROPID__FF100001 = new GetNumber() { FNumber = auxNumber } },
                    FUnitID = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FQty = qty,
                    FLot = new GetNumber() { FNumber = lotNumber },
                    FSrcStockId = new GetNumber() { FNumber = fromStockNumber },
                    //调出仓位
                    FSrcStockLocId = new FSrcStockLocId() { FSRCSTOCKLOCID__FF100002 = new GetNumber() { FNumber = srcStockLocNumber } },
                    FDestStockId = new GetNumber() { FNumber = StockID == null ? "" : StockID["number"].ToString() },
                    //调入仓位
                    FDestStockLocId = new FDestStockLocId() { FDESTSTOCKLOCID__FF100002 = new GetNumber() { FNumber = stockLocNumber } },
                    FSrcStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FDestStockStatusId = new GetNumber() { FNumber = KDStockStatus.KCZT01_SYS.ToString() },
                    FOwnerTypeOutId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FOwnerTypeId = KDOwnerType.BD_OwnerOrg.ToString(),
                    FOwnerId = new GetNumber() { FNumber = stockOrgNumber },
                    FBaseUnitId = new GetNumber() { FNumber = unt == null ? "" : unt["number"].ToString() },
                    FBaseQty = qty,
                    FKeeperTypeId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperId = new GetNumber() { FNumber = stockOrgNumber },
                    FKeeperTypeOutId = KDOwnerType.BD_KeeperOrg.ToString(),
                    FKeeperOutId = new GetNumber() { FNumber = fromOrgNumber },
                    FDestMaterialId = new GetNumber() { FNumber = mat == null ? "" : mat["number"].ToString() }
                };
                model.Model.FBillEntry.Add(rowItem);
            }
            string json = JsonConvert.SerializeObject(model);
            return json;
        }

        /// <summary>
        /// 加载所有列
        /// </summary>
        /// <param name="e"></param>
        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(this.Context, this.BusinessInfo.GetForm().Id);
            var fieldKeyList = meta.BusinessInfo.GetBosFields().Select(x => x.Field.Key).ToList();
            for (int i = 0; i < fieldKeyList.Count; i++)
            {
                e.FieldKeys.Add(fieldKeyList[i]);
            }
        }
    }
}
